//
// Created by Administrator on 2021/11/12.
// May Saint Diana bless you!
//
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>

using namespace std;

class Solution {
public:
    vector<int> nums;

    Solution(vector<int> &nums) {
        this->nums = nums;
    }

    /** Resets the array to its original configuration and return it. */
    vector<int> reset() {
        return nums;
    }

    /** Returns a random shuffling of the array. */
    vector<int> shuffle() {
        vector<int> res = vector<int>(nums);
        int n = (int) nums.size();
        for (int i = 0; i < n; i++) {
            int pos = rand() % (n - i) + i;
            swap(res, i, pos);
        }

        return res;
    }

    void swap(vector<int> &nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
};

class Solution1 {
public:
    Solution1(vector<int> &nums) {
        data = nums;
        this->nums = nums;
    }

    /** Resets the array to its original configuration and return it. */
    vector<int> reset() {
        return data;
    }

    /** Returns a random shuffling of the array. */
    vector<int> shuffle() {
        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(nums.begin(), nums.end(), g);
        return nums;
    }

private:
    vector<int> nums;
    vector<int> data;
};

class Solution2 {
public:
    vector<int> tmp_nums, original;

    int getRandInt(int min, int max) {
        return rand() % (max - min) + min;
    }

    Solution2(vector<int> &nums) {
        original = nums;
        tmp_nums = nums;
    }

    /** Resets the array to its original configuration and return it. */
    vector<int> reset() {
        tmp_nums = original;
        return original;
    }

    /** Returns a random shuffling of the array. */
    vector<int> shuffle() {
        for (int i = 0; i < tmp_nums.size(); ++i)
            swap(tmp_nums[i], tmp_nums[getRandInt(i, tmp_nums.size())]);
        return tmp_nums;
    }
};


/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(nums);
 * vector<int> param_1 = obj->reset();
 * vector<int> param_2 = obj->shuffle();
 */
int main() {
    vector<int> nums{1, 2, 3};
    auto *sol = new Solution(nums);
    auto param1 = sol->shuffle();
    auto param2 = sol->reset();
    for (const auto &x:param1)
        cout << x << " ";
    cout << endl;
    for (const auto &x:param2)
        cout << x << " ";
    cout << endl;
    return 0;
}


